
#include "StdAfx.h"
#include "PhysicsModule.h"
#include "PhysXFileOutTerminal.h"
#include "PredefinedEngineSystemMessages.h"
#include "PredefinedGameDataMessages.h"

#include "PhysicsPart.h"


//=>Physics
#include "PMM_PhysicsModuleCreated.h"
#include "PMM_PhysicsModuleCreated_Return.h"
#include "CollisionMessages.h"
#include "PhysicsPropertyMessages.h"
//<=

//=>GAME

#include "GMM_AttachActorTo.h"
#include "GMM_DetachActorFrom.h"
//<=

//=>UI
#include "UMM_DebugCommand.h"
//<=

//=>Render
#include "RMM_DebugRendererCreated.h"
//<=



namespace _MODULE_
{
	namespace _PHYSICS_
	{
		NxVec3 NxDIRECTION_FRONT,NxDIRECTION_RIGHT,NxDIRECTION_UP;
		NxMat33 g_DebugTranform;

		PhysicsModule::PhysicsModule(void)
			:aEngineModule(_FOGGE_::eEMID_Physics,__T("PhysicsModule"))
		{
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_PHYSICS_::PhysicsPartFactory);

			//for dummydata
			i_GDBAccesser->RegisterDataPartFactory(foNEW _DATAPARTFACTORY_::_PHYSICS_::DummyPhysicsPartFactory);


	
        /**
			predefined Message handlers
		*/
		//@{
			_DATAPARTFACTORY_::_PHYSICS_::PhysicsPartFactory::g_BasePath=_T(".\\data\\physics\\");
			RegisterHandler(_PESMSG::ePESM_Activate,&PhysicsModule::OnWindowActivate);
			RegisterHandler(_PGDMSG::ePGDM_DataLoaded,&PhysicsModule::OnDataLoaded);
			RegisterHandler(_PGDMSG::ePGDM_DataRemoved,&PhysicsModule::OnDataRemoved);
			//RegisterHandler(_PGDMSG::ePGDM_DataModified,&PhysicsModule::OnDataModified);
		//@} 


		/**
			Collision Message handlers
		*/
		//@{
			RegisterHandler(_PMMSG::ePMM_SetCollisionCheck,&PhysicsModule::OnSetCollisionCheck);
			RegisterHandler(_PMMSG::ePMM_SetActorCollisionGroup,&PhysicsModule::OnSetActorCollisionGroup);
			RegisterHandler(_PMMSG::ePMM_SubscribeForCollisionReport,&PhysicsModule::OnSubscribeForCollisionReport);
			RegisterHandler(_PMMSG::ePMM_PointCollisionCheck,&PhysicsModule::OnPointCollisionCheck);
			RegisterHandler(_PMMSG::ePMM_LineCollisionCheck,&PhysicsModule::OnLineCollisionCheck);
			RegisterHandler(_PMMSG::ePMM_ActorCollisionCheck,&PhysicsModule::OnActorCollisionCheck);
			
		//@}	

			
		/**
			Physics Property Message handlers
		*/
		//@{
			RegisterHandler(_PMMSG::ePMM_ChangeVelocity,&PhysicsModule::OnChangeVelocity);
			RegisterHandler(_PMMSG::ePMM_ChangeAngularVelocity,&PhysicsModule::OnChangeAngularVelocity);
		//@}	

		/**
			UIModlue Message handlers
		*/
		//@{
			RegisterHandler(_UMMSG::eUMM_DebugCommand,&PhysicsModule::OnDebugCommand);
		//@}

		/**
			RenderModlue Message handlers
		*/
		//@{
			RegisterHandler(_RMMSG::eRMM_DebugRendererCreated,&PhysicsModule::OnDebugRendererCreated);
		//@}

		/**
			GameModlue Message handlers
		*/
		//@{
			RegisterHandler(_GMMSG::eGMM_AttachActorTo,&PhysicsModule::OnAttachActorTo);
		//@}

			

			i_DebugRender=NULL;

			// model's direction vector is need to save
			NxDIRECTION_FRONT.set(&_FOMATH::DIRECTION_FRONT.x);
			NxDIRECTION_RIGHT.set(&_FOMATH::DIRECTION_RIGHT.x);
			NxDIRECTION_UP.set(&_FOMATH::DIRECTION_UP.x);



			/*_MODULE_::_PHYSICS_::PhysX_FromEulerAnglesYZX(g_DebugTranform,
						PhysXDegToRad(-90),PhysXDegToRad(0),PhysXDegToRad(-90));*/
			g_DebugTranform.id();

			
		}

		PhysicsModule::~PhysicsModule(void)
		{
		}
////////////////////////////////////////
		/*virtual*/
		bool PhysicsModule::Initialize()
		{
			m_bIsInitialized = true;

			
			
			return true;
		}
	/////////////////////////////
		/*virtual*/
		bool PhysicsModule::SystemInitialize()
		{

			
			//install logger
			_FOGGE_::_UTIL_::Logger* ptrNewLogger=foNEW _FOGGE_::_UTIL_::Logger(_FOGGE_::_UTIL_::Logger::eLL_Develop,__T("PhysicsModuleLogger"));
			ptrNewLogger->AttachTerminal(foNEW _FOGGE_::_UTIL_::FileOutTerminal(__T("PhysicsModule.log"),0));
			_FOGGE_::_GO_::g_ptrLogger->AttachLoggerToChain(ptrNewLogger);

			PhysXFileOutTerminal* ptrPhysXFileOutTerminal=foNEW PhysXFileOutTerminal(__T("PhysXLog.log"),0);
			ptrNewLogger=foNEW _FOGGE_::_UTIL_::Logger(_FOGGE_::_UTIL_::Logger::eLL_Develop,__T("PhysicsModuleLogger"));
			ptrNewLogger->AttachTerminal(ptrPhysXFileOutTerminal);
			_FOGGE_::_GO_::g_ptrLogger->AttachLoggerToChain(ptrNewLogger);


			


			// Initialize PhysicsSDK
			NxPhysicsSDKDesc desc;
			NxSDKCreateError errorCode = NXCE_NO_ERROR;
			m_ptrPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, NULL, ptrPhysXFileOutTerminal, desc, &errorCode);
			if(m_ptrPhysicsSDK == NULL) 
			{
				assert(!__T("\nSDK create error.\nUnable to initialize the PhysX SDK, exiting the sample.\n\n"));
				return false;
			}
	
			m_ptrPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.05f);
			// Set the debug visualization parameters
			m_ptrPhysicsSDK->setParameter(NX_VISUALIZATION_SCALE, 1);
			m_ptrPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_SHAPES, 1);
			m_ptrPhysicsSDK->setParameter(NX_VISUALIZE_ACTOR_AXES, 1);
			m_ptrPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_FNORMALS, 1);
			m_ptrPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_VNORMALS, 1);
			

			m_ptrPhysicsSDK->setParameter(NX_VISUALIZE_CONTACT_POINT, 1);
			m_ptrPhysicsSDK->setParameter(NX_VISUALIZE_CONTACT_NORMAL, 1);
			m_ptrPhysicsSDK->setParameter(NX_VISUALIZE_ACTOR_AXES, 1);
			

			// Create a scene
			NxSceneDesc sceneDesc;
			sceneDesc.gravity				= NxVec3(0.0f, 0, 0.0f);
			sceneDesc.simType				= NX_SIMULATION_HW;
			m_ptrScene = m_ptrPhysicsSDK->createScene(sceneDesc);

			if(!m_ptrScene){ 
				sceneDesc.simType				= NX_SIMULATION_SW; 
				m_ptrScene = m_ptrPhysicsSDK->createScene(sceneDesc);  

				if(!m_ptrScene)
				{
					assert(!_T("\nError: Unable to create a PhysX scene .\n\n"));
					return false;
				}
			}

			
			

			// Set default material
			NxMaterial* defaultMaterial = m_ptrScene->getMaterialFromIndex(0);
			defaultMaterial->setRestitution(0.0f);
			defaultMaterial->setStaticFriction(0.5f);
			defaultMaterial->setDynamicFriction(0.5f);

	

			//create querys

			NxSceneQueryDesc SQD;
			SQD.setToDefault();
			SQD.report=this;
			SQD.executeMode=NX_SQE_SYNCHRONOUS;
			m_ptrSceneQueryImmediate=m_ptrScene->createSceneQuery(SQD); 

			if(m_ptrSceneQueryImmediate == NULL) 
			{
				assert(!_T("\nError: Unable to create a PhysX SceneQuery(NX_SQE_SYNCHRONOUS).\n\n"));
				return false;
			}


			SQD.executeMode=NX_SQE_ASYNCHRONOUS;
			m_ptrSceneQueryBatch=m_ptrScene->createSceneQuery(SQD); 
			if(m_ptrSceneQueryBatch == NULL) 
			{
				assert(!_T("\nError: Unable to create a PhysX SceneQuery(NX_SQE_ASYNCHRONOUS).\n\n"));
				return false;
			}
 
 


			//initialize factory
			_DATAPARTFACTORY_::_PHYSICS_::PhysicsPartFactory::g_ptrPhysicsSDK=m_ptrPhysicsSDK;
			_DATAPARTFACTORY_::_PHYSICS_::PhysicsPartFactory::g_ptrScene=m_ptrScene;



			//when physx baseunit size is 1cm
			//
			m_fGlobalmultiplier=5;


			//initialize debug renderer
			m_bRenderDebugInfo=false;
			

			
			m_iMaxDebugVertexCount=1024*5;
			m_ptrTempVertexBuffer=foNEW _FOGGE_::DEBUGVERTEX[m_iMaxDebugVertexCount];



			return true;
		}
		/////////////////////////////////////////////////////////
		/*virtual*/
		void PhysicsModule::Finalize()
		{
			
		}
		/////////////////////////////////////////////////


		/*virtual*/
		void PhysicsModule::SystemFinalize()
		{
			if(m_ptrTempVertexBuffer)
				foDELETEA(m_ptrTempVertexBuffer);

			if(m_ptrPhysicsSDK != NULL)
			{

				
				//release scenquerys
				if(m_ptrSceneQueryImmediate)
					m_ptrScene->releaseSceneQuery (*m_ptrSceneQueryImmediate);
				if(m_ptrSceneQueryBatch)
					m_ptrScene->releaseSceneQuery (*m_ptrSceneQueryBatch);

				if(m_ptrScene != NULL) 
					m_ptrPhysicsSDK->releaseScene(*m_ptrScene);
				m_ptrScene = NULL;
				NxReleasePhysicsSDK(m_ptrPhysicsSDK);
				m_ptrPhysicsSDK = NULL;
			}
		}

		///////////////////////////////////////////////////

		void PhysicsModule::GetPhysicsResults()
		{
			// Get results from gScene->simulate(gDeltaTime)
			while (!m_ptrScene->fetchResults(NX_RIGID_BODY_FINISHED, false))
				Sleep(0);
		}

		/*virtual*/
		void PhysicsModule::Update(float elapsedtime)
		{
			if(m_ptrScene==NULL)
				return;

			int nbActors = m_ptrScene->getNbActors();
			NxActor** actors = m_ptrScene->getActors();
			while(nbActors--)
			{
				NxActor* actor = *actors++;
				if(!actor->userData) continue;
				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=(_DATAPART_::_PHYSICS_::PhysicsPart*)actor->userData;
				if(ptrPhysicsPart->AmIMasterPart())
				{
					ptrPhysicsPart->UpdateVelocity(elapsedtime);
					ptrPhysicsPart->UpdateAngularVelocity(elapsedtime);
				}
			}

			if(m_bRenderDebugInfo)
			{
				DrawPhysicsDebugInfo();
			}

			// Start simulation (non blocking)
			m_ptrScene->simulate(elapsedtime);

			
			// Fetch simulation results
			m_ptrScene->flushStream();

			//wait 
			GetPhysicsResults();

			//do Update physics actor
			// Render all actors
			nbActors = m_ptrScene->getNbActors();
			actors = m_ptrScene->getActors();
			while(nbActors--)
			{
				NxActor* actor = *actors++;
				if(!actor->userData) continue;
				if(actor->isSleeping()) continue;
				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=(_DATAPART_::_PHYSICS_::PhysicsPart*)actor->userData;
				
				ptrPhysicsPart->Update(elapsedtime);
			}
		}

		////////////////////////////////////////////////////

		/*virtual*/
		void PhysicsModule::PostUpdate(float elapsedtime)
		{
			ProcessPostedMessage(GetMyID());
		}

		////////////////////////////////////////////////////////////

		HRESULT PhysicsModule::OnWindowActivate(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			return S_OK;
		}

		/////////////Physx event handler////////
		void PhysicsModule::onContactNotify(NxContactPair& pair, NxU32 events)
		{
			_PMMSG::PMM_CollisionCheckResult *ptrCCR=FoDynamicCast(_PMMSG::PMM_CollisionCheckResult,GetNewMassage(_PMMSG::ePMM_CollisionCheckResult));	

			_PMMSG::PMM_CollisionCheckResult::CollisionInfo info;



			if(pair.actors[0])
			{
				info.collideActor = (_FOGGE_::_GDB_::foDataObject*)pair.actors[0]->userData;
				//if(Object)	Object->events = events;
			}

			if(pair.actors[1])
			{
				info.collideActor2= (_FOGGE_::_GDB_::foDataObject*)pair.actors[1]->userData;
				//if(Object)	Object->events = events;
			}
			
			NxContactStreamIterator i(pair.stream);
    
			while(i.goNextPair()) // user can call getNumPairs() here 
			{
				while(i.goNextPatch()) // user can also call getShape() and getNumPatches() here
				{
					//user can also call getPoint() and getSeparation() here
					const NxVec3& contactNormal = i.getPatchNormal();

					info.collideNormal.set(contactNormal.x,contactNormal.y,contactNormal.z);
					while(i.goNextPoint())
					{
						//user can also call getPoint() and getSeparation() here
						const NxVec3& contactPoint = i.getPoint();

						info.collideLocation.set(contactPoint.x,contactPoint.y,contactPoint.z);
						info.index=-1;//this is contect info
						ptrCCR->m_CollisionInfoVector.push_back(info);
				
					}
				}
			}

			ptrCCR->PushReceiver(_FOGGE_::eEMID_Game);
			SendMessage(ptrCCR);
		

		}

		/////////////Physx event handler////////
		void PhysicsModule::onTrigger(NxShape& triggerShape, NxShape& otherShape, NxTriggerFlag status)
		{

		}

		////////////////////////////////////

		NxQueryReportResult  PhysicsModule::onBooleanQuery (void *userData, bool result)
		{
			return NX_SQR_CONTINUE ;
		}
		NxQueryReportResult  PhysicsModule::onRaycastQuery (void *userData, NxU32 nbHits, const NxRaycastHit *hits)
		{
			return NX_SQR_CONTINUE ;
		}
		NxQueryReportResult  PhysicsModule::onShapeQuery (void *userData, NxU32 nbHits, NxShape **hits)
		{
			return NX_SQR_CONTINUE ;
		}
		NxQueryReportResult  PhysicsModule::onSweepQuery (void *userData, NxU32 nbHits, NxSweepQueryHit *hits)
		{
			return NX_SQR_CONTINUE ;
		}

		/////////////////////
		HRESULT PhysicsModule::OnDataLoaded(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PGDMSG::PGDM_DataLoaded *ptrDL=FoDynamicCast(_PGDMSG::PGDM_DataLoaded,ptrMsg);

			_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrDL->m_ptrDataObject->GetDataPart(_FOGGE_::eEMID_Physics));
			ptrPhysicsPart->GetOwner()->IncRefCount();

			ptrPhysicsPart->m_ptrNxActor->putToSleep();

			return S_OK;
		}
		HRESULT PhysicsModule::OnDataRemoved(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PGDMSG::PGDM_DataRemoved *ptrDR=FoDynamicCast(_PGDMSG::PGDM_DataRemoved,ptrMsg);


			_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrDR->m_ptrDataObject->GetDataPart(_FOGGE_::eEMID_Physics));
			m_ptrScene->releaseActor(*ptrPhysicsPart->m_ptrNxActor);
			
			
			return S_OK;
		}
		///////////////////
/*		HRESULT PhysicsModule::OnDataModified(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PGDMSG::PGDM_DataModified *ptrDM=FoDynamicCast(_PGDMSG::PGDM_DataModified ,ptrMsg);

			_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrDM->m_ptrDataObject->GetDataPart(_FOGGE_::eEMID_Physics));

			bool isKinematic=ptrPhysicsPart->m_ptrNxActor->readBodyFlag(NX_BF_KINEMATIC);


			
			if(ptrPhysicsPart->GetOwner()->GetModifiedFlag()|_FOGGE_::_GDB_::foDataObject::eBP_Location)
			{
				_FOMATH::Vector location;
				location=ptrPhysicsPart->GetOwner()->GetLocation();
				
			
				NxVec3 newloc(location.getVector());

				if(isKinematic)
				{
					
					ptrPhysicsPart->m_ptrNxActor->moveGlobalPosition(newloc);
				}
				else
				{
					ptrPhysicsPart->m_ptrNxActor->setGlobalPosition(newloc);
				}
			}
			if(ptrPhysicsPart->GetOwner()->GetModifiedFlag()|_FOGGE_::_GDB_::foDataObject::eBP_Rotation)
			{
				float pitch,yaw,roll;
				_FOMATH::Rotator rotation;
				rotation=ptrPhysicsPart->GetOwner()->GetRotation();

				
				NxMat33 rot;

				PhysX_FromEulerAnglesYZX(rot,PhysXDegToRad(rotation.m_fYaw),PhysXDegToRad(rotation.m_fRoll),PhysXDegToRad(rotation.m_fPitch));
				
				if(isKinematic)
				{
					ptrPhysicsPart->m_ptrNxActor->moveGlobalOrientation(rot);
				}
				else
				{
					ptrPhysicsPart->m_ptrNxActor->setGlobalOrientation(rot);
				}
				


			}
			return S_OK;
		}*/

		////////////////////////////////////////////

		HRESULT PhysicsModule::OnDebugCommand(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_UMMSG::UMM_DebugCommand *ptrDC=FoDynamicCast(_UMMSG::UMM_DebugCommand,ptrMsg);

			if(ptrDC->m_DebugCommand==_T("ToggleRenderPhysicsActors"))
			{
				m_bRenderDebugInfo=!m_bRenderDebugInfo;
			}

			return S_OK;

		}

		///////////////////////////////////////////////////////////////

		HRESULT PhysicsModule::OnDebugRendererCreated(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_RMMSG::RMM_DebugRendererCreated *ptrDRC=FoDynamicCast(_RMMSG::RMM_DebugRendererCreated,ptrMsg);

			i_DebugRender=ptrDRC->i_DebugRender;

			return S_OK;
		}

		////////////////////////////////////////

		HRESULT PhysicsModule::OnSetCollisionCheck(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_SetCollisionCheck *ptrTCC=FoDynamicCast(_PMMSG::PMM_SetCollisionCheck,ptrMsg);

			
			if(ptrTCC->m_ptrDataObject1&&ptrTCC->m_ptrDataObject2)
			{//by acrot pair

				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart1=
					FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrTCC->m_ptrDataObject1->GetDataPart(_FOGGE_::eEMID_Physics));

				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart2=
					FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrTCC->m_ptrDataObject2->GetDataPart(_FOGGE_::eEMID_Physics));

				NxU32 flag=m_ptrScene->getActorPairFlags(*ptrPhysicsPart1->m_ptrNxActor,*ptrPhysicsPart2->m_ptrNxActor);


				if(ptrTCC->m_bCollision)
					flag&=~NX_IGNORE_PAIR;
				else
					flag|=NX_IGNORE_PAIR;

				m_ptrScene->setActorPairFlags(*ptrPhysicsPart1->m_ptrNxActor,*ptrPhysicsPart2->m_ptrNxActor,flag);
				


			}
			else
			{//by group pair
				m_ptrScene->setGroupCollisionFlag(ptrTCC->m_wGroupID1,ptrTCC->m_wGroupID2,ptrTCC->m_bCollision);
			}

			return S_OK;
		}

		HRESULT PhysicsModule::OnSetActorCollisionGroup(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_SetActorCollisionGroup *ptrSACG=FoDynamicCast(_PMMSG::PMM_SetActorCollisionGroup,ptrMsg);


			
			for(int i=0;i<ptrSACG->m_ActorInfoVector.size();i++)
			{
				_PMMSG::PMM_SetActorCollisionGroup::ActorInfo& info=ptrSACG->m_ActorInfoVector[i];

				assert(info.ptrDataObject&&__T("info.m_ptrDataObject is NULL"));

				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=
						FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,info.ptrDataObject->GetDataPart(_FOGGE_::eEMID_Physics));



				assert((info.wGroupID>=0&&info.wGroupID<32)&&__T("info.wGroupID is not in bound!!"));

				//set shape's group
				NxShape *const* arrayShape=ptrPhysicsPart->m_ptrNxActor->getShapes();
				for(int i=0;i<ptrPhysicsPart->m_ptrNxActor->getNbShapes();i++)
				{
					arrayShape[i]->setGroup(info.wGroupID);
				}

				//set actor's group
				ptrPhysicsPart->m_ptrNxActor->setGroup(info.wGroupID);
			}
			return S_OK;
		}
	
		HRESULT PhysicsModule::OnSubscribeForCollisionReport(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_SubscribeForCollisionReport *ptrSCR=FoDynamicCast(_PMMSG::PMM_SubscribeForCollisionReport,ptrMsg);	

			if(ptrSCR->m_ptrDataObject1&&ptrSCR->m_ptrDataObject2)
			{//by acrot pair
				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart1=
					FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrSCR->m_ptrDataObject1->GetDataPart(_FOGGE_::eEMID_Physics));

				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart2=
					FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrSCR->m_ptrDataObject2->GetDataPart(_FOGGE_::eEMID_Physics));

				NxU32 flag=m_ptrScene->getActorPairFlags(*ptrPhysicsPart1->m_ptrNxActor,*ptrPhysicsPart2->m_ptrNxActor);

				if(ptrSCR->m_bWhenOnTouch)
					flag|=NX_NOTIFY_ON_TOUCH;
				else
					flag&=~NX_NOTIFY_ON_TOUCH;

				if(ptrSCR->m_bWhenStartTouch)
					flag|=NX_NOTIFY_ON_START_TOUCH;
				else
					flag&=~NX_NOTIFY_ON_START_TOUCH;

				if(ptrSCR->m_bWhenEndTouch)
					flag|=NX_NOTIFY_ON_END_TOUCH;
				else
					flag&=~NX_NOTIFY_ON_END_TOUCH;

				m_ptrScene->setActorPairFlags(*ptrPhysicsPart1->m_ptrNxActor,*ptrPhysicsPart2->m_ptrNxActor,flag);
			}
			else
			{//by group pair
				NxU32 flag=m_ptrScene->getActorGroupPairFlags(ptrSCR->m_wGroupID1,ptrSCR->m_wGroupID2);

				if(ptrSCR->m_bWhenOnTouch)
					flag|=NX_NOTIFY_ON_TOUCH;
				else
					flag&=~NX_NOTIFY_ON_TOUCH;

				if(ptrSCR->m_bWhenStartTouch)
					flag|=NX_NOTIFY_ON_START_TOUCH;
				else
					flag&=~NX_NOTIFY_ON_START_TOUCH;

				if(ptrSCR->m_bWhenEndTouch)
					flag|=NX_NOTIFY_ON_END_TOUCH;
				else
					flag&=~NX_NOTIFY_ON_END_TOUCH;

				m_ptrScene->setActorGroupPairFlags(ptrSCR->m_wGroupID1,ptrSCR->m_wGroupID2,flag);
			}
			return S_OK;
		}
		HRESULT PhysicsModule::OnPointCollisionCheck(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_PointCollisionCheck *ptrPCC=FoDynamicCast(_PMMSG::PMM_PointCollisionCheck,ptrMsg);	

			_PMMSG::PMM_CollisionCheckResult *ptrCCR=NULL;

			if(ptrMsg!=NULL&&FoIsExactKindOf(_PMMSG::PMM_CollisionCheckResult,ptrMsg))
			{
				ptrCCR=FoDynamicCast(_PMMSG::PMM_CollisionCheckResult,ptrMsg);	
			}
		
			for(int i=0;ptrPCC->m_PointVector.size();i++)
			{
				_FOMATH::Vector& point=ptrPCC->m_PointVector[i];

				if(ptrCCR)
				{//process query in immediate mode
					//raycastAnyShape
					//raycastClosestShape
					//raycastAllShapes
					NxRaycastHit hitresult;

					NxRay ray;
					ray.orig.set(point.getVector());
					//this check is for point,point has no direction. so just set world up vector
					ray.dir.set(0,1,0);
			
					NxShape* ptrHittedShape=m_ptrSceneQueryImmediate->raycastClosestShape(ray,NX_ALL_SHAPES,hitresult,-1,0.1f,
					NX_RAYCAST_SHAPE|NX_RAYCAST_IMPACT|NX_RAYCAST_NORMAL);

					if(ptrHittedShape)
					{//there is a collision
						_PMMSG::PMM_CollisionCheckResult::CollisionInfo collisioninfo;

						collisioninfo.index=i;//set index
						collisioninfo.collideActor=static_cast<_FOGGE_::_GDB_::foDataObject*>(ptrHittedShape->getActor().userData);
						collisioninfo.collideLocation.set(hitresult.worldImpact.x,hitresult.worldImpact.y,hitresult.worldImpact.z);
						collisioninfo.collideNormal.set(hitresult.worldNormal.x,hitresult.worldNormal.y,hitresult.worldNormal.z);
						collisioninfo.collideDist=0;
						ptrCCR->m_CollisionInfoVector.push_back(collisioninfo);//append
					}

				}
				else
				{//process query in batch mode

					NxRaycastHit hitresult;

					NxRay ray;
					ray.orig.set(point.getVector());
					//this check is for point,point has no direction. so just set world up vector
					ray.dir.set(0,1,0);
					m_ptrSceneQueryBatch->raycastClosestShape(ray,NX_ALL_SHAPES,hitresult,-1,0.1f,
					NX_RAYCAST_SHAPE|NX_RAYCAST_IMPACT|NX_RAYCAST_NORMAL);
				}

			}
			return S_OK;
		}
		HRESULT PhysicsModule::OnLineCollisionCheck(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_LineCollisionCheck *ptrLCC=FoDynamicCast(_PMMSG::PMM_LineCollisionCheck,ptrMsg);	

			_PMMSG::PMM_CollisionCheckResult *ptrCCR=NULL;

			if(ptrMsg!=NULL&&FoIsExactKindOf(_PMMSG::PMM_CollisionCheckResult,ptrMsg))
			{
				ptrCCR=FoDynamicCast(_PMMSG::PMM_CollisionCheckResult,ptrMsg);	
			}
				
		
			for(int i=0;ptrLCC->m_LineVector.size();i++)
			{
				_PMMSG::PMM_LineCollisionCheck::Line& line=ptrLCC->m_LineVector[i];

				if(ptrCCR)
				{//process query in immediate mode
					
					NxRaycastHit hitresult;

					NxRay ray;
					NxVec3 lStart(line.start.getVector());
					NxVec3 lEnd(line.end.getVector());
					ray.orig=lStart;

					ray.dir=lEnd-lStart;
					NxReal length=ray.dir.normalize();
					
					
					NxShape* ptrHittedShape=m_ptrSceneQueryImmediate->raycastClosestShape(ray,NX_ALL_SHAPES,hitresult,-1,length,
					NX_RAYCAST_SHAPE|NX_RAYCAST_IMPACT|NX_RAYCAST_NORMAL|NX_RAYCAST_DISTANCE);

					if(ptrHittedShape)
					{//there is a collision
						_PMMSG::PMM_CollisionCheckResult::CollisionInfo collisioninfo;

						collisioninfo.index=i;//set index
						collisioninfo.collideActor=static_cast<_FOGGE_::_GDB_::foDataObject*>(ptrHittedShape->getActor().userData);
						collisioninfo.collideLocation.set(hitresult.worldImpact.x,hitresult.worldImpact.y,hitresult.worldImpact.z);
						collisioninfo.collideNormal.set(hitresult.worldNormal.x,hitresult.worldNormal.y,hitresult.worldNormal.z);
						collisioninfo.collideDist=hitresult.distance;
						ptrCCR->m_CollisionInfoVector.push_back(collisioninfo);//append
					}

				}
				else
				{//process query in batch mode

					NxRaycastHit hitresult;

					NxRay ray;
					NxVec3 lStart(line.start.getVector());
					NxVec3 lEnd(line.end.getVector());
					ray.orig=lStart;

					ray.dir=lEnd-lStart;
					NxReal length=ray.dir.normalize();
					
					
					m_ptrSceneQueryImmediate->raycastClosestShape(ray,NX_ALL_SHAPES,hitresult,-1,length,
					NX_RAYCAST_SHAPE|NX_RAYCAST_IMPACT|NX_RAYCAST_NORMAL|NX_RAYCAST_DISTANCE);
				}
			}

			return S_OK;
		}
		HRESULT PhysicsModule::OnActorCollisionCheck(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_ActorCollisionCheck *ptrACC=FoDynamicCast(_PMMSG::PMM_ActorCollisionCheck,ptrMsg);	

			_PMMSG::PMM_CollisionCheckResult *ptrCCR=NULL;

			if(ptrMsg!=NULL&&FoIsExactKindOf(_PMMSG::PMM_CollisionCheckResult,ptrMsg))
			{
				ptrCCR=FoDynamicCast(_PMMSG::PMM_CollisionCheckResult,ptrMsg);	
			}
				
		
			for(int i=0;ptrACC->m_ActorVector.size();i++)
			{
				_FOGGE_::_GDB_::foDataObject* ptrDataObject=ptrACC->m_ActorVector[i];
				_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=
					FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrDataObject->GetDataPart(_FOGGE_::eEMID_Physics));

				if(ptrCCR)
				{//process query in immediate mode
					

					NxShape *const* arrayShape=ptrPhysicsPart->m_ptrNxActor->getShapes();
					NxBounds3 actorWorldBound;
					for(int j=0;j<ptrPhysicsPart->m_ptrNxActor->getNbShapes();j++)
					{
						NxBounds3 tempBound;
						arrayShape[j]->getWorldBounds(tempBound);

						actorWorldBound.combine(tempBound);
					}
					
					bool result=m_ptrSceneQueryImmediate->checkOverlapAABB( actorWorldBound);
						
					if(result)
					{//there is a collision
						_PMMSG::PMM_CollisionCheckResult::CollisionInfo collisioninfo;

						//set data
						collisioninfo.index=i;//set index
						collisioninfo.collideActor=NULL;
						collisioninfo.collideLocation.reset();
						collisioninfo.collideNormal.reset();
						collisioninfo.collideDist=0;
						ptrCCR->m_CollisionInfoVector.push_back(collisioninfo);//append
					}

				}
				else
				{//process query in batch mode

					NxShape *const* arrayShape=ptrPhysicsPart->m_ptrNxActor->getShapes();
					NxBounds3 actorWorldBound;
					for(int i=0;i<ptrPhysicsPart->m_ptrNxActor->getNbShapes();i++)
					{
						NxBounds3 tempBound;
						arrayShape[i]->getWorldBounds(tempBound);

						actorWorldBound.combine(tempBound);
					}
					
					m_ptrSceneQueryImmediate->checkOverlapAABB( actorWorldBound);
				}
			}
			return S_OK;
		}
		/////////////////////////////////////////////

		HRESULT PhysicsModule::OnChangeVelocity(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_ChangeVelocity *ptrCV=FoDynamicCast(_PMMSG::PMM_ChangeVelocity,ptrMsg);

			_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=
				FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrCV->m_ptrObject->GetDataPart(_FOGGE_::eEMID_Physics));

			if(ptrPhysicsPart==NULL)
				return S_OK;

			ptrPhysicsPart->SetToNewMaster();
			
			ptrPhysicsPart->m_vVelocity.set(&ptrCV->m_vVelocity.x);

			
			return S_OK;
		}
		
		HRESULT PhysicsModule::OnChangeAngularVelocity(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_PMMSG::PMM_ChangeAngularVelocity *ptrCAV=FoDynamicCast(_PMMSG::PMM_ChangeAngularVelocity,ptrMsg);

			_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsPart=
				FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrCAV->m_ptrObject->GetDataPart(_FOGGE_::eEMID_Physics));
		
			
			ptrPhysicsPart->SetToNewMaster();

			ptrPhysicsPart->m_rAngularVelocity=ptrCAV->m_rAngularVelocity;

			return S_OK;
		}

	
		/////////////////////////////////////////////
		HRESULT PhysicsModule::OnAttachActorTo(_FOGGE_::_MSG_::Message* ptrMsg,_FOGGE_::_MSG_::Message* ptrRetMsg)
		{
			_GMMSG::GMM_AttachActorTo *ptrAA=FoDynamicCast(_GMMSG::GMM_AttachActorTo ,ptrMsg);

			_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsBase=
				FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrAA->m_ptrDataAttachBase->GetDataPart(_FOGGE_::eEMID_Physics));
			_DATAPART_::_PHYSICS_::PhysicsPart* ptrPhysicsToAttach=
				FoDynamicCast(_DATAPART_::_PHYSICS_::PhysicsPart,ptrAA->m_ptrDataToAttach->GetDataPart(_FOGGE_::eEMID_Physics));

			if(ptrPhysicsBase&&ptrPhysicsToAttach)
			{
		/*		NxFixedJointDesc fixedDesc;    
				fixedDesc.actor[0] = ptrPhysicsBase->m_ptrNxActor;    
				fixedDesc.actor[1] = ptrPhysicsToAttach->m_ptrNxActor;    
				NxVec3 dd;
				dd.set(100,0,0);
				fixedDesc.setGlobalAnchor(dd);
				fixedDesc.setGlobalAxis(NxVec3(0,0,0));
				NxFixedJoint *fixedJoint=(NxFixedJoint*)m_ptrScene->createJoint(fixedDesc);*/

				ptrPhysicsBase->AttachChild(ptrPhysicsToAttach,NULL);
			}
			/*else if(ptrPhysicsToAttach)
			{//child is not null,but parent is null
				ptrPhysicsToAttach->SetParent(ptrAA->m_ptrDataAttachBase);
			}
			else if(ptrPhysicsBase)
			{//base is not null but noneed to job
			}*/
			//
			return S_OK;
		}
		
		/////////////////////////////////////////////

		HRESULT PhysicsModule::DrawPhysicsDebugInfo(void)
		{

			
			int vertexIndex=0;

			const NxDebugRenderable *ptrDebugRenderableInfo=m_ptrScene->getDebugRenderable();
			if(ptrDebugRenderableInfo)
			{
				//render points	
				NxU32 NbPoints = ptrDebugRenderableInfo->getNbPoints();
				if(NbPoints>0)
				{
					const NxDebugPoint* Points = ptrDebugRenderableInfo->getPoints();            

					vertexIndex=0;
					for(int i=0;i<NbPoints;i++,vertexIndex++)
					{          
						if(vertexIndex>=m_iMaxDebugVertexCount)
						{//flush buffer
							i_DebugRender->AddPoints(m_ptrTempVertexBuffer,vertexIndex);
							vertexIndex=0;
						}
						m_ptrTempVertexBuffer[vertexIndex].color=Points->color;

						m_ptrTempVertexBuffer[vertexIndex].v.set(Points->p.x,Points->p.y,Points->p.z);
						Points++;            
					}

					i_DebugRender->AddPoints(m_ptrTempVertexBuffer,vertexIndex);
					
				}

				
				
				// Render lines        
				NxU32 NbLines = ptrDebugRenderableInfo->getNbLines();   
				if(NbLines>0)
				{
					const NxDebugLine* Lines = ptrDebugRenderableInfo->getLines();            

					vertexIndex=0;
					for(int iline=0;iline<NbLines;iline++)
					{      

						if(vertexIndex>=m_iMaxDebugVertexCount)
						{//flush buffer
							i_DebugRender->AddLines(m_ptrTempVertexBuffer,vertexIndex/2);
							vertexIndex=0;
						}
						m_ptrTempVertexBuffer[vertexIndex].color=Lines->color;
						m_ptrTempVertexBuffer[vertexIndex++].v.set(Lines->p0.x,Lines->p0.y,Lines->p0.z);

						m_ptrTempVertexBuffer[vertexIndex].color=Lines->color;
						m_ptrTempVertexBuffer[vertexIndex++].v.set(Lines->p1.x,Lines->p1.y,Lines->p1.z);

						Lines++;
					}

					i_DebugRender->AddLines(m_ptrTempVertexBuffer,vertexIndex/2);
				}
				

				
							
				// Render triangles        
				NxU32 NbTris = ptrDebugRenderableInfo->getNbTriangles();     
				if(NbTris>0)
				{
					const NxDebugTriangle* Triangles = ptrDebugRenderableInfo->getTriangles();     

					vertexIndex=0;
					for(int itri=0;itri<NbTris;itri++)
					{   
						if(vertexIndex>=m_iMaxDebugVertexCount)
						{//flush buffer
							i_DebugRender->AddTriangles(m_ptrTempVertexBuffer,vertexIndex/3);
							vertexIndex=0;
						}

						m_ptrTempVertexBuffer[vertexIndex].color=Triangles->color;
						m_ptrTempVertexBuffer[vertexIndex++].v.set(Triangles->p0.x,Triangles->p0.y,Triangles->p0.z);

						m_ptrTempVertexBuffer[vertexIndex].color=Triangles->color;
						m_ptrTempVertexBuffer[vertexIndex++].v.set(Triangles->p1.x,Triangles->p1.y,Triangles->p1.z);

						m_ptrTempVertexBuffer[vertexIndex].color=Triangles->color;
						m_ptrTempVertexBuffer[vertexIndex++].v.set(Triangles->p2.x,Triangles->p2.y,Triangles->p2.z);

						Triangles++;
					}

					i_DebugRender->AddTriangles(m_ptrTempVertexBuffer,vertexIndex/3);
				}


				return S_OK;
			}
			else
			{
				return S_FALSE;
			}
		}

		
	}
}
